/**
 * 一开始考虑到用外部排序，但记录文件本身不大，可以装载进内存
 * 为了提高效率，最后决定使用归并排序
 * 89：mfunc方法用于执行记录读入和结果写入
 * 171：merge方法用于合并操作
 * 206：mergesort方法用于归并排序
 */


import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class MergeSort {

    //内部类Node,若要对标题索引记录文件排序则取消注释
    /*public class Node{
        private String title;  //标题
        private String idNum;  //索引编号

        //Node类的构造函数，初始化对象属性
        public Node(String t,String id){
            this.title=t;
            this.idNum=id;
        }
        
        //返回title
        public String getTitle(){
            return this.title;
        }

        //返回idNum
        public String getIdNum(){
            return this.idNum;
        }

    }*/

    //内部类Node,若要对作者索引记录文件排序则取消注释
    public class Node{
        private String name="";  //作者名
        private List<Integer> p=new ArrayList<Integer>();  //作者关联文章的索引编号

        //Node类的构造函数，初始化对象属性
        public Node(String name,List<Integer> p){
            this.name=name;
            for(int element:p){
                this.p.add(element);
            }
        }

        //返回name
        public String getName(){
            return this.name;
        }

        //返回p
        public List<Integer> getP(){
            return this.p;
        }
    }

    private List<Node> lis=new ArrayList<Node>();  //存储标题记录的列表
    private BufferedReader br=null;  //文件读取缓冲区
    private BufferedWriter bw=null;  //文件写入缓冲区
    
    private String path="./data/author/author.txt";  //记录文件路径，若要对标题排序，路径改为"./data/title.txt";另一个路径："./data/author/author.txt"
    private String wrpath="";  //写入文件夹路径
    private int count=0;  //计数变量
    private static int num1=0;   //计数变量
    private static int num2=0;   //计数变量

    public MergeSort(String filepath){
        this.wrpath=filepath;
        mfunc(path);
    }

    /**
     * 执行方法
     */
    public void mfunc(String path){
        //读取文件内容到内存
        try{
            File infile=new File(path);
            br=new BufferedReader(new InputStreamReader(new FileInputStream(infile)));
            String line="";
            //String t="";
            //String idn="";
            String name="";
            List<Integer> p=new ArrayList<Integer>();
            while((line=br.readLine())!=null){
                count++;

                //若要对标题记录排序，则取消注释
                /*if((count)%2==1){
                    idn=line;
                }else{
                    t=line;
                    lis.add(new Node(t,idn));
                }*/

                //若要对作者记录排序，则取消注释
                String[] strarray=line.split("#");
                for(int i=0;i<strarray.length;i++){ 
                    if(i==0) name=strarray[i];
                    else{
                        int n=Integer.parseInt(strarray[i]);
                        p.add(n);
                    } 
                }
                lis.add(new Node(name,p));
                name="";
                p.clear();
            }
        }catch(IOException e){
            e.printStackTrace();
        }finally{
            try{
                br.close();
            }catch(IOException e){
                e.printStackTrace();
            }
        }
        mergesort(lis,0,count/2-1);  //开始排序
        //把最终排序结果写入到文件中
        try{
            Iterator<Node> it=lis.iterator();  //创建迭代器
			while(it.hasNext()) {
                //文件跳转
                if(num1%10000==0){
                    //String fpath=wrpath+"/index_"+num2+".txt";
                    String fpath=wrpath+"/aindex_"+num2+".txt";
                    File infile=new File(fpath);
                    bw=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(infile,true),"utf-8"));
                    num2++;
                }
                Node temp=it.next();
                String s=temp.getName();
                Iterator<Integer> iterator=temp.getP().iterator();
                while(iterator.hasNext()){
                    s+=("#"+iterator.next().toString());
                }
				bw.write(s+"\n");
                bw.flush();
                num1++;
                s="";
                
                /*Node temp=it.next();
                String s=temp.getIdNum()+","+temp.getTitle();
                bw.write(s+"\n");
                bw.flush();
                num1++;
                s="";*/
            }
		}catch(IOException e){
			e.printStackTrace();
		}finally{
			try{
				bw.close();
			}catch(IOException e){
				e.printStackTrace();
			}
		}

    }

    /**
     * 合并算法
     */
    public void merge(List<Node> lis,int low,int mid,int high){

        //先声明几个需要用到的变量
        List<Node> temp=new ArrayList<Node>();  //临时列表
        int s=low;  //前半部份列表
        int t=mid+1;  //后半部分列表

        //下面开始做合并操作
        while(s<=mid||t<=high){
            if(s<=mid&&t<=high){
                if(lis.get(s).getName().compareTo(lis.get(t).getName())<=0){
                    temp.add(lis.get(s));
                    s++;
                }else{
                    temp.add(lis.get(t));
                    t++;
                }
            }else if(s<=mid&&t>high){
                temp.add(lis.get(s));
                s++;
            }else if(s>mid&&t<=high){
                temp.add(lis.get(t));
                t++;
            }
        }

        //把临时列表里面的值转移到lis中
        for(int i=0;i<temp.size();i++){
            lis.set(low+i,temp.get(i));
        }
    }

    /**
     * 排序算法
     */
    public void mergesort(List<Node> lis,int low,int high){
        if(low<high){
            mergesort(lis,low,(low+high)/2);
            mergesort(lis,(low+high)/2+1,high);
            merge(lis,low,(low+high)/2,high);
        }
    }
}